home *** CD-ROM | disk | FTP | other *** search
- /********************************************************************
- * *
- * Drag and drop protocol routines *
- * for MiNT and MultiTOS desktops only *
- * *
- * BUGS/CAVEATS: *
- * This code is not re-entrant (it uses a static variable for the *
- * pipe name and for saving the SIGPIPE signal handler) *
- * *
- * While doing the drag and drop, the SIGPIPE signal (write on an *
- * empty pipe) is ignored *
- * *
- * Copyright (C) 1992, Atari Corporation *
- * *
- * Since these are Atari's routines, these will not be modified. *
- * WinLIB PRO's Drag-and-drop protocol will be used in DDWINLIB.C *
- * *
- ********************************************************************/
-
- #include <tos.h>
- #include <string.h>
- #include "winlib.h"
-
- #ifndef Word
- #define Word short
- #define Long long
- #endif
-
- #ifndef EACCDN
- #define EACCDN -36
- #endif
-
- #ifndef SIGPIPE
- #define SIGPIPE 13
- #endif
-
- #ifndef SIG_IGN
- #define SIG_IGN 1L
- #endif
-
- #ifndef WF_OWNER
- #define WF_OWNER 20
- #endif
-
- #ifndef FA_HIDDEN
- #define FA_HIDDEN 0x2
- #endif
-
- extern int gl_apid;
-
- static char pipename[] = "U:\\PIPE\\DRAGDROP.AA";
- static long oldpipesig;
-
- #ifdef DEBUGGING
- #define debug_alert(x, y) form_alert(x, y)
- #else
- #define debug_alert(x, y)
- #endif
-
- /* Code for originator */
-
- /*
- * Create a pipe for doing the drag-and-drop, and send an AES
- * message to the recipient application telling it about the drag-
- * and-drop operation.
- *
- * Input Parameters:
- * apid: AES id of the window owner
- * winid: target window (0 for background)
- * msx, msy: mouse X and Y position (or -1, -1 if a fake drag-and-
- * drop)
- * kstate: shift key state at time of event
- *
- * Output Parameters:
- * exts: A 32 byte buffer into which the receipient's 8 favorite
- * extensions will be copied.
- *
- * Returns:
- * A positive file descriptor (of the opened drag-and-drop pipe) on
- * success.
- * -1 if the receipient doesn't respond or returns DD_NAK
- * -2 if appl_write fails
- */
-
- GLOBAL int ddcreate(int apid, int winid, int msx, int msy, int kstate, char exts[])
- {
- int fd, i;
- int msg[8];
- long fd_mask;
- char c;
-
- pipename[17] = pipename[18] = 'A';
- fd = -1;
- do {
- pipename[18]++;
- if (pipename[18] > 'Z') {
- pipename[17]++;
- if (pipename[17] > 'Z')
- break;
- }
- /* FA_HIDDEN means "get EOF if nobody has pipe open for reading" */
- fd = (int)(Fcreate(pipename, FA_HIDDEN));
- } while (fd == EACCDN);
-
- if (fd < 0) {
- debug_alert(1, "[1][Fcreate error][OK]");
- return fd;
- }
-
- /* Construct and send the AES message */
- msg[0] = AP_DRAGDROP;
- msg[1] = gl_apid;
- msg[2] = 0;
- msg[3] = winid;
- msg[4] = msx;
- msg[5] = msy;
- msg[6] = kstate;
- msg[7] = (pipename[17] << 8) | pipename[18];
- i = appl_write(apid, 16, msg);
- if (i == 0) {
- debug_alert(1, "[1][appl_write error][OK]");
- Fclose(fd);
- return -2;
- }
-
- /* Now wait for a response */
- fd_mask = 1L << fd;
- i = Fselect(DD_TIMEOUT, &fd_mask, 0L, 0L);
- if (!i || !fd_mask) { /* Timeout happened */
- debug_alert(1, "[1][ddcreate: Fselect timeout][OK]");
- abort_dd:
- Fclose(fd);
- return -1;
- }
-
- /* Read the 1 byte response */
- i = (int)(Fread(fd, 1L, &c));
- if (i != 1 || c != DD_OK) {
- if (i != 1)
- debug_alert(1, "[1][ddcreate: read error][OK]");
- else
- debug_alert(1, "[1][ddcreate: DD_NAK][OK]");
- goto abort_dd;
- }
-
- /* Now read the "preferred extensions" */
- i = (int)(Fread(fd, DD_EXTSIZE, exts));
- if (i != DD_EXTSIZE) {
- debug_alert(1, "[1][Error reading extensions][OK]");
- goto abort_dd;
- }
-
- oldpipesig = Psignal(SIGPIPE, SIG_IGN);
- return fd;
- }
-
-
- /*
- * See if the recipient is willing to accept a certain type of data
- * (as indicated by "ext")
- *
- * Input parameters:
- * fd file descriptor returned from ddcreate()
- * ext pointer to the 4 byte file type
- * name pointer to the name of the data
- * size number of bytes of data that will be sent
- *
- * Output parameters: none
- *
- * Returns:
- * DD_OK if the receiver will accept the data
- * DD_EXT if the receiver doesn't like the data type
- * DD_LEN if the receiver doesn't like the data size
- * DD_NAK if the receiver aborts
- */
-
- GLOBAL int ddstry(int fd, char *ext, char *name, long size)
- {
- Word hdrlen, i;
- char c;
-
- /* 4 bytes for extension, 4 bytes for size, 1 byte for trailing 0 */
- hdrlen = 9 + strlen(name);
- i = Fwrite(fd, 2L, &hdrlen);
-
- /* Now send the header */
- if (i != 2) return DD_NAK;
- i = Fwrite(fd, 4L, ext);
- i += Fwrite(fd, 4L, &size);
- i += Fwrite(fd, (long)strlen(name)+1, name);
- if (i != hdrlen) return DD_NAK;
-
- /* Wait for a reply */
- i = Fread(fd, 1L, &c);
- if (i != 1) return DD_NAK;
- return c;
- }
-
- /*
- * Close a drag-and-drop operation
- */
- GLOBAL void ddclose(int fd)
- {
- (void)Psignal(SIGPIPE, oldpipesig);
- (void)Fclose(fd);
- }
-
- /*
- * open a drag-and-drop pipe
- *
- * Input Parameters:
- * ddnam: the pipe's name (from the last word of
- * the AES message)
- * preferext: a list of DD_NUMEXTS 4 byte extensions we understand
- * these should be listed in order of preference
- * if we like fewer than DD_NUMEXTS extensions, the
- * list should be padded with 0s
- *
- * Output Parameters: none
- *
- * Returns:
- * A (positive) file handle for the drag & drop pipe, on success
- * -1 if the drag & drop is aborted
- * A negative error number if an error occurs while opening the
- * pipe.
- */
- GLOBAL int ddopen(int ddnam, char *preferext)
- {
- int fd;
- char outbuf[DD_EXTSIZE+1];
-
- pipename[18] = ddnam & 0x00ff;
- pipename[17] = (ddnam & 0xff00) >> 8;
-
- fd = (int)(Fopen(pipename, 2));
- if (fd < 0) return fd;
-
- outbuf[0] = DD_OK;
- strncpy(outbuf+1, preferext, DD_EXTSIZE);
-
- oldpipesig = Psignal(SIGPIPE, SIG_IGN);
-
- if (Fwrite(fd, (long)DD_EXTSIZE+1, outbuf) != DD_EXTSIZE+1) {
- ddclose(fd);
- return -1;
- }
-
- return fd;
- }
-
- /*
- * ddrtry: Get the next header from the drag-and-drop originator
- *
- * Input Parameters:
- * fd: the pipe handle returned from ddopen()
- *
- * Output Parameters:
- * name: a pointer to the name of the drag & drop item
- * (note: this area must be at least DD_NAMEMAX bytes long)
- * whichext: a pointer to the 4 byte extension
- * size: a pointer to the size of the data
- *
- * Returns:
- * 0 on success
- * -1 if the originator aborts the transfer
- *
- * Note: it is the caller's responsibility to actually send the
- * DD_OK byte to start the transfer, or to send a DD_NAK, DD_EXT, or
- * DD_LEN reply with ddreply().
- */
-
- GLOBAL int ddrtry(int fd, char *name, char *whichext, long *size)
- {
- Word hdrlen;
- int i;
- char buf[80];
-
- i = (int)(Fread(fd, 2L, &hdrlen));
- if (i != 2) {
- return -1;
- }
- if (hdrlen < 9) { /* This should never happen */
- return -1;
- }
- i = (int)(Fread(fd, 4L, whichext));
- if (i != 4) {
- return -1;
- }
- whichext[4] = 0;
- i = (int)(Fread(fd, 4L, size));
- if (i != 4) {
- return -1;
- }
- hdrlen -= 8;
- if (hdrlen > DD_NAMEMAX)
- i = DD_NAMEMAX;
- else
- i = hdrlen;
- if (Fread(fd, (long)i, name) != i) {
- return -1;
- }
- hdrlen -= i;
-
- /* Skip any extra header */
- while (hdrlen > 80) {
- Fread(fd, 80L, buf);
- hdrlen -= 80;
- }
- if (hdrlen > 0)
- Fread(fd, (long)hdrlen, buf);
-
- return 0;
- }
-
- /*
- * send a 1 byte reply to the drag & drop originator
- *
- * Input Parameters:
- * fd: file handle returned from ddopen()
- * ack: byte to send (e.g. DD_OK)
- *
- * Output Parameters: none
- *
- * Returns: 0 on success, -1 on failure
- * in the latter case the file descriptor is closed
- */
-
- GLOBAL int ddreply(int fd, int ack)
- {
- char c = ack;
-
- if (Fwrite(fd, 1L, &c) != 1L) {
- Fclose(fd);
- }
- return 0;
- }